
module design_test(
    button0,
    button1,
    button2,
    button3,
    clk_100mhz,
    uart_tx,
    rstn
);
input button0;
input button1;
input button2;
input button3;
input clk_100mhz;
output uart_tx;
input rstn;

reg [7:0] data_q;
reg vld;
wire press;
reg press_q;

simple_uart_clk100mhz_250000 u_uart(
    .clk(clk_100mhz),
    .rstn(rstn),
    .data(data_q),
    .vld(vld),
    .tx(uart_tx)
);

assign press = ~(button0 & button1 & button2 & button3);

always @(posedge clk_100mhz) begin
    if (rstn & press ) begin
        press_q <= 1'b1;
    end else begin
        press_q <= 1'b0;
    end 
    //  else if (press) begin
    //     press_q <= 1'b1;
    // end else if (press_q) begin
    //     press_q <= 1'b0; // 只保留一个采样周期, 使得置位vld, 启动传输数据
    // end
end

always @(posedge clk_100mhz) begin
    if (~rstn) begin
        vld <= 1'b0;
    end else if (press_q & ~press) begin // 按键已释放, 但是记录了上一拍的按键状态,由此来检查是否该发送数据;这里会不会有问题呢,值得思考?
        vld <= 1'b1;
    end else begin
        vld <= 1'b0;
    end
end

always @(posedge clk_100mhz) begin
    case ({button3, button2, button1, button0})
        4'b1110: data_q <= 8'd1;
        4'b1101: data_q <= 8'd2;
        4'b1011: data_q <= 8'd3;
        4'b0111: data_q <= 8'd4;
        // default:
        //     $finish(); // what
        // default: data_q <= data_q;
    endcase
end
endmodule

module simple_uart_clk100mhz_250000 (
    clk,
    rstn,
    data,
    vld,
    tx
);

input clk;
input rstn;
input [7:0] data;
input vld;
output tx;

// 250000 baud rate
// clk 100MHz
// div: 100MHz / 250000 = 400   
parameter div = 400;
reg clk_div;
reg [8:0] count;

reg tx_q;
reg [7:0] data_q;
reg vld_q;
reg [3:0] tx_bit; // 

assign tx = tx_q;

// 分频时钟,产生baud时钟
always @(posedge clk) begin
    if (~rstn) begin
        clk_div <= 1'b0;
        count <= 1'b0;
    end else begin
        if(count<(div/2-1)) begin
            // clk_div <= clk_div;
            count <= count + 1;
        end else begin
            clk_div <= ~clk_div;
            count <= 9'd0;
        end
    end
end

always @(posedge clk ) begin
    if (~rstn) begin
        vld_q <= 1'b0;
        data_q <= 8'b0;
    end else begin 
        if (vld & ~vld_q) begin
            vld_q <= vld;
            data_q <= data;
        end else if (vld_q && tx_bit[3:0]>4'd9) begin
            vld_q <= 1'b0;
        end
    end
end

always @(posedge clk) begin
    if (~rstn) begin
        tx_bit <= 4'b0;
    end
end

always @(posedge clk_div) begin
    if (rstn) begin
        if (vld_q) begin
                tx_bit[3:0] <= tx_bit[3:0] + 1;
        end else begin
            tx_bit[3:0] <= 4'b0;
        end
    end
end

always @(*) begin
    case ({vld_q,tx_bit[3:0]})
        5'h10: tx_q = 1'b0; // start_bit
        5'h11: tx_q = data_q[0]; // data from low bit to high bit
        5'h12: tx_q = data_q[1];
        5'h13: tx_q = data_q[2];
        5'h14: tx_q = data_q[3];
        5'h15: tx_q = data_q[4];
        5'h16: tx_q = data_q[5];
        5'h17: tx_q = data_q[6];
        5'h18: tx_q = data_q[7];
        5'h19: tx_q = 1'b1; // stop_bit
        default: 
            tx_q = 1'b1;
    endcase
end

endmodule
